package com.zomato.photofilters.imageprocessors.subfilters;

import com.zomato.photofilters.geometry.Point;
import com.zomato.photofilters.imageprocessors.ImageProcessor;
import com.zomato.photofilters.imageprocessors.SubFilter;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.PixelMap;

/**
 * @author varun
 * Subfilter to tweak rgb channels of an image
 */
public class ToneCurveSubFilter implements SubFilter {
    private static String tag = "";
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.DEBUG, 0, "ToneCurveSubFilter");

    private static int rgbFlag = 0;
    private static int rFlag = 0;
    private static int gFlag = 0;
    private static int bFlag = 0;
    private static int Flag = 0;

    // These are knots which contains the plot points
    private Point[] rgbKnots;
    private Point[] greenKnots;
    private Point[] redKnots;
    private Point[] blueKnots;
    private int[] rgb;
    private int[] r;
    private int[] g;
    private int[] b;

    /**
     * Initialise ToneCurveSubfilter (NOTE : Don't pass null knots, pass straight line instead)
     * Knots are the points in 2D taken by tweaking photoshop channels(plane ranging from 0-255)
     *
     * @param rgbKnots   rgb Knots
     * @param redKnots   Knots in Red Channel
     * @param greenKnots Knots in green Channel
     * @param blueKnots  Knots in Blue channel
     */
    public ToneCurveSubFilter(Point[] rgbKnots, Point[] redKnots, Point[] greenKnots,
                              Point[] blueKnots) {
        Point[] straightKnots = new Point[2];
        straightKnots[0] = new Point(0, 0);
        straightKnots[1] = new Point(255, 255);
        if (rgbKnots == null) {
            this.rgbKnots = straightKnots;
        } else {
            this.rgbKnots = rgbKnots;
        }
        if (redKnots == null) {
            this.redKnots = straightKnots;
        } else {
            this.redKnots = redKnots;
        }
        if (greenKnots == null) {
            this.greenKnots = straightKnots;
        } else {
            this.greenKnots = greenKnots;
        }
        if (blueKnots == null) {
            this.blueKnots = straightKnots;
        } else {
            this.blueKnots = blueKnots;
        }
    }


    @Override
    public PixelMap process(PixelMap inputImage, boolean flag) {
        rgbKnots = sortPointsOnXAxis(rgbKnots);
        redKnots = sortPointsOnXAxis(redKnots);
        greenKnots = sortPointsOnXAxis(greenKnots);
        blueKnots = sortPointsOnXAxis(blueKnots);
        if (flag == true) {
            Flag = Flag % 5;
            Flag++;
        }
        HiLog.info(LABEL, "  Flag = " + Flag);
        if (rgb == null) {
            // rgb = BezierSpline.curveGenerator(rgbKnots);
            rgbFlag++;
            switch (Flag) {
                case 1:
                    rgb = CurvedPath.curvedPath0;
                    break;
                case 2:
                case 4:
                    rgb = CurvedPath.curvedPathSame;
                    break;
                case 3:
                    rgb = CurvedPath.curvedPath8;
                    break;
                case 5:
                    rgb = CurvedPath.curvedPath16;
                    break;
                default:
                    break;
            }
        }

        if (r == null) {
            // r = BezierSpline.curveGenerator(redKnots);
            rFlag++;
            switch (Flag) {
                case 1:
                case 4:
                    r = CurvedPath.curvedPathSame;
                    break;
                case 2:
                    r = CurvedPath.curvedPath5;
                    break;
                case 3:
                    r = CurvedPath.curvedPath9;
                    break;
                case 5:
                    r= CurvedPath.curvedPath17;
                    break;
                default:
                    break;
            }

        }

        if (g == null) {
            // g = BezierSpline.curveGenerator(greenKnots);
            gFlag++;
            switch (Flag) {
                case 1:
                case 2:
                case 4:
                    g = CurvedPath.curvedPathSame;
                    break;
                case 3:
                    g = CurvedPath.curvedPath10;
                    break;
                case 5:
                    g = CurvedPath.curvedPath18;
                    break;
                default:
                    break;
            }
        }

        if (b == null) {
            // b = BezierSpline.curveGenerator(blueKnots);
            bFlag++;
            switch (Flag) {
                case 1:
                case 2:
                    b = CurvedPath.curvedPathSame;
                    break;
                case 3:
                    b = CurvedPath.curvedPath11;
                    break;
                case 4:
                    b = CurvedPath.curvedPath15;
                    break;
                case 5:
                    b = CurvedPath.curvedPath19;
                    break;
                default:
                    break;
            }
        }

        return ImageProcessor.applyCurves(rgb, r, g, b, inputImage);
    }

    public Point[] sortPointsOnXAxis(Point[] points) {
        if (points == null) {
            return null;
        }
        for (int s = 1; s < points.length - 1; s++) {
            for (int k = 0; k <= points.length - 2; k++) {
                if (points[k].x > points[k + 1].x) {
                    float temp = 0;
                    temp = points[k].x;
                    points[k].x = points[k + 1].x; //swapping values
                    points[k + 1].x = temp;
                }
            }
        }
        return points;
    }

    @Override
    public String getTag() {
        return tag;
    }

    @Override
    public void setTag(Object tag) {
        ToneCurveSubFilter.tag = (String) tag;
    }
}
